/*******************************************************************************
 * Copyright (c) 2007, Geophysical Center RAS
 * Sergey Berezin, Dmitry Voitsekhovskiy
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms,
 * with or without modification, are permitted provided
 * that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * - Neither the name of the Geophysical Center RAS nor the names
 * of its contributors may be used to endorse or promote products
 * derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using VisualEsse.DataEngine.Types;

namespace VisualEsse.DataEngine
{
    public class GenericMetadataProvider : MetadataProvider, IComplexSelector     
    {
        private List<EsseParameterDescription> parameters;
        private EsseMetadataProvider esseProvider;

        private TemporalGrid time;
        private GeoUniformGrid2d spatial;

        public GenericMetadataProvider(string homeDirectory, TemporalGrid time, GeoUniformGrid2d spatial)
        {
            this.time = time;
            this.spatial = spatial;

            parameters = new List<EsseParameterDescription>();
            esseProvider = EsseMetadataProvider.CreateEsseMetadataProvider(homeDirectory);
        }

        public GenericMetadataProvider(string homeDirectory, TemporalGrid time, GeoUniformGrid2d spatial, EsseMetadataProvider esseMetadata)
        {
            this.time = time;
            this.spatial = spatial;

            parameters = new List<EsseParameterDescription>();
            esseProvider = esseMetadata;
        }

        public void AddParameter(EsseParameter parameter)
        {            
            EsseParameterDescription epd = esseProvider.Exists(parameter) ?
                esseProvider.GetDescription(parameter) :
                new EsseParameterDescription(parameter, "", parameter.Name, "", PaletteDescription.Default);
            parameters.Add(epd);
        }

        public void AddParameter(EsseParameterDescription parameter)
        {
            parameters.Add(parameter);
        }

        public override EsseParameterDescription GetDescription(string localKey, int level)
        {
            int i =
                parameters.FindIndex(
                delegate(EsseParameterDescription epd)
                {
                    return epd.Level == level && epd.LocalKey == localKey;
                });

            if (i < 0)
                throw new ArgumentException("Metadata doesn't containts requested parameter " + localKey + " for " + level + " coordinates!");
            return parameters[i];
        }

        public override EsseParameterDescription GetDescription(string name, string verticalCoordName, int level)
        {
            int i =
                parameters.FindIndex(
                    delegate(EsseParameterDescription item)
                    {
                        return item.Name == name && item.VerticalCoord.Name == verticalCoordName && item.Level == level;
                    });

            if(i < 0)
                throw new ArgumentException("Metadata doesn't containts requested parameter " + name + " for " + verticalCoordName + " coordinates!");
            return parameters[i];
        }

        public override bool Exists(EsseParameter parameter)
        {
            return parameters.FindIndex(
                delegate(EsseParameterDescription epd)
                {
                    return epd.EsseParameter.Equals(parameter);
                }) >= 0;
        }

        public override TemporalGrid TemporalGrid
        {
            get { return time; }
        }

        public override GeoUniformGrid2d SpatialGrid
        {
            get { return spatial; }
        }

        #region IComplexSelector Members

        public int Levels
        {
            get { return 1; }
        }

        public System.Collections.IEnumerable ValuesAtLevel(int level, object[] values)
        {
            if (level == 0)
            {
                foreach (EsseParameterDescription epd in parameters)
                {
                    yield return epd;
                }
            }
            else
            {
                yield return values[0];
            }
        }

        public object[] Find(object value)
        {
            EsseParameterDescription p = value as EsseParameterDescription;
            return new object[] { p, p };
        }

        public int GetNumberOfValuesAtLevel(int level, object[] values)
        {
            if (level == 0)
            {
                return parameters.Count;
            }

            return 1;
        }

        #endregion
    }
}
